Link to this headingGovee_H617A

manufacturer = “0388ec000a0101”
ble_mac = “c9:38:33:33:4d:70”

Link to this headingHandles

┌──────────────┬────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────┬────────────────────────────────────────────────┐
│ Handles │ Service > Characteristics │ Properties │ Data │
├──────────────┼────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────────────┤
│ 0001 -> 0009 │ Generic Access ( 00001800-0000-1000-8000-00805f9b34fb ) │ │ │
│ 0003 │ Device Name ( 00002a00-0000-1000-8000-00805f9b34fb ) │ READ WRITE │ u’Govee_H617A_4D70’ │
│ 0005 │ Appearance ( 00002a01-0000-1000-8000-00805f9b34fb ) │ READ WRITE │ Unknown │
│ 0007 │ Peripheral Preferred Connection Parameters ( 00002a04-0000-1000-8000-00805f9b34fb ) │ READ │ Connection Interval: 8 -> 10 │
│ │ │ │ Slave Latency: 0 │
│ │ │ │ Connection Supervision Timeout Multiplier: 400 │
│ 0009 │ 2ac9 ( 00002ac9-0000-1000-8000-00805f9b34fb ) │ READ │ ‘’ │
│ │ │ │ │
│ 000a -> 000d │ Generic Attribute ( 00001801-0000-1000-8000-00805f9b34fb ) │ │ │
│ 000c │ Service Changed ( 00002a05-0000-1000-8000-00805f9b34fb ) │ READ INDICATE │ │
│ │ │ │ │
│ 000e -> 0016 │ 00010203-0405-0607-0809-0a0b0c0d1910 │ │ │
│ 0010 │ 00010203-0405-0607-0809-0a0b0c0d2b10 │ NOTIFY READ │ ‘’ │
│ 0014 │ 00010203-0405-0607-0809-0a0b0c0d2b11 │ NOTIFY READ WRITE NO RESPONSE WRITE │ ‘’ │
│ │ │ │ │
│ 0017 -> 0021 │ 02f00000-0000-0000-0000-00000000fe00 │ │ │
│ 0019 │ 02f00000-0000-0000-0000-00000000ff03 │ READ │ ‘’ │
│ 001b │ 02f00000-0000-0000-0000-00000000ff02 │ NOTIFY READ │ u’ntf_enable’ │
│ 001f │ 02f00000-0000-0000-0000-00000000ff00 │ READ │ ‘’ │
│ 0021 │ 02f00000-0000-0000-0000-00000000ff01 │ WRITE NO RESPONSE WRITE │ │
│ │ │ │ │
└──────────────┴────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────┴────────────────────────────────────────────────┘

Link to this headingTests

00002ac9-0000-1000-8000-00805f9b34fb: ????

00010203-0405-0607-0809-0a0b0c0d2b10: Rx
00010203-0405-0607-0809-0a0b0c0d2b11: Tx

02f00000-0000-0000-0000-00000000ff03
02f00000-0000-0000-0000-00000000ff02
02f00000-0000-0000-0000-00000000ff00
02f00000-0000-0000-0000-00000000ff01

Link to this headingReceive UUID

00010203-0405-0607-0809-0a0b0c0d2b10: Receive UUID

Get Auth Key???

Link to this headingSend UUID

00010203-0405-0607-0809-0a0b0c0d2b11: Send UUID

Link to this headingNFT Enable???

>>> python notify.py --address "c9:38:33:33:4d:70" 02f00000-0000-0000-0000-00000000ff02 2024-11-23 20:59:25,319 __main__ INFO: starting scan... 2024-11-23 20:59:25,455 __main__ INFO: connecting to device... 2024-11-23 20:59:26,111 __main__ INFO: Connected 2024-11-23 20:59:26,223 __main__ INFO: Unknown: bytearray(b'ntf_enable') 2024-11-23 20:59:26,223 __main__ INFO: Read[02f00000-0000-0000-0000-00000000ff02]: bytearray(b'ntf_enable') 2024-11-23 20:59:31,263 __main__ INFO: Unknown: bytearray(b'ntf_enable') 2024-11-23 20:59:31,263 __main__ INFO: Read[02f00000-0000-0000-0000-00000000ff02]: bytearray(b'ntf_enable')

Link to this headingCommands

AA010000000000000000000000000000000000AB: Keep Alive sent every 2 secs

330502 RED GREEN BLUE 00FFAE54000000000000000000(31 ^ RED ^ GREEN ^ BLUE)
Set to Red

  • AA: Get Value

    • 01: is_on

      • On: AA0101
      • Off: AA0100
    • 04: get_brightness

      • 1%: AA0401
      • 100%: AA0464
    • 05: Get Mode

      • 0407: Scene Mode Scene 7 romantic
    • 06: get_device_fw_version

      • Version: 3.02.24
    • 0703: hw_version

      • Version: 3.01.01
    • 0e: ???

      • ???: 0f
    • 11: ???

      • ???: 001e0f0f
    • 12: ???

      • ????: 00640000800a
    • 23: Current Colors?

      • Red: 0000000080
    • 40: ???

      • ???: 000f
    • a3: ???

      • ???: 01
    • a5: Number of Segments

      • 1501: 15 Segments starting at 01
    • a501: Get Segment 1

      • 64ff8d0b 64aa5511 64ff8d0b: (Brightness | Red | Green | Blue) 15 segments
    • a502: Get Segment 2

      • 64ff8d0b 64aa5511 64aa5511
    • a503: Get Segment 3

      • 64ff0000 64ff8d0b 64ff8d0b
    • a504: Get Segment 4

      • 64ff8d0b 64ff8d0b 64ff8d0b
    • a505: Get Segment 5

      • 64ff8d0b 64ff8d0b 64ff8d0b
    • b1: Auth_key?

      • No data
    • ee: ???

      • ???: 000a01
    • ff: ???

      • No data
  • 33: Write

    • 0100: Power Off
    • 0101: Power On
    • 04: Brightness
      • 1%: 01
      • 100% 64
    • 0504: Set Scene
      • 00: Sunrise
      • 01: Sunset
    • 051501: Segment Color Mode
      • 00FFFF 0000000000 3200: RRGGBB padding Number of segments

aa23ff:
- Command: Notify (aa23): ff00000080000000800000008000000080
- Unexpected response: b’\xaa#\xff\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80’

aa1200:
- Command: Notify (aa12): 00640000800a
- Unexpected response: b’\xaa\x12\x00d\x00\x00\x80\n’

aa1100:
- Command: Notify (aa11): 001e0f0f
- Unexpected response: b’\xaa\x11\x00\x1e\x0f\x0f’

330914:
- Unexpected response: b’3\t’

330914
330914

aa0400
aa0501
aa0f00
aa1100
aa1200
aa23ff
aa4100

Link to this headingScript

import asyncio from bleak import BleakScanner, BleakClient # UUIDs for the target device characteristics NOTIFY_UUID = "00010203-0405-0607-0809-0a0b0c0d2b10" WRITE_UUID = "00010203-0405-0607-0809-0a0b0c0d2b11" TARGET_NAME = "Govee_H617A" scenes = { "Sunrise": "00", "Sunset": "01", "Nightlight": "02", "Movie": "04", "Dating": "05", "Romantic": "07", "Illumination": "3f", "Cheerful": "40", } #Commands for H617A command_list = { #Write Commands "turn_on": "330101", "turn_on2": "3301ff", "turn_off": "330100", "turn_off2": "3301f0", "set_brightness": "3304", #01-64 "set_scene": "330504", # Scene number "set_color": "33051501", #00-Fe red, 00-Fe green, 00-Fe blue "set_music_mode": "3305130663", #"set_color": "33050d", #00-Fe red, 00-Fe green, 00-Fe blue "set_auth": "33b2", #Read Commands "is_on": "aa01", # Padding, checkbyte "get_brightness": "aa04", "get_rgb": "aa0501", "get_device_fw_version": "aa06", "hw_version": "aa0703", "get_auth_key": "aab1", #Multi Command #"setcolor": "", #"setlevel": "", "getinfo": "818a8b", } async def notification_handler(sender, data): """Callback for handling notifications.""" hex_data = data.hex() resp = None current_command = "Unknown" for command, hex_info in command_list.items(): if hex_data.startswith(hex_info): current_command = command resp = hex_data[len(hex_info):] break if current_command != "is_on": print(f"Notify[2b10]: {current_command} {resp}") def finalze_message(message): #Do checksum math check = 0 bmessage = bytearray.fromhex(message) for x in bmessage: check ^= int(x) #Pad Data untill its 19 bytes lone return bmessage.ljust(19, b"\x00") + check.to_bytes(1, 'little') def segemnts2num(seg_array): out = 0 #Set Segments by Binary for x in seg_array: out |= (1 << x) return (out & 0xff7f).to_bytes(2, 'little').hex() async def write_loop(client, timeout=2): """Send data to the write characteristic every 2 seconds.""" while client.is_connected : try: await client.write_gatt_char(WRITE_UUID, finalze_message(command_list["is_on"])) #print(f"Sending Keep Alive payload to {WRITE_UUID}: {KEEP_ALIVE_MESSAGE}") except Exception as e: print(f"Error sending Keep Alive payload: {e}") break await asyncio.sleep(timeout) async def write_and_read(client, data): try: full_message = finalze_message(data) # Write the payload to the characteristic print(f"TX[2b11]: {full_message.hex()}") await client.write_gatt_char(WRITE_UUID, full_message) #response = await client.read_gatt_char(WRITE_UUID) #print(f"RX[2b11] data: {response.hex()}") #return response except Exception as e: print(f"Error in write_and_read: {e}") #return None async def find_and_subscribe(): print("Scanning for BLE devices...") devices = await BleakScanner.discover() # Search for the target device # Search for the target device target_device = next((d for d in devices if TARGET_NAME in d.name), None) if not target_device: print(f"No device found with name containing '{TARGET_NAME}'") return async with BleakClient(target_device.address) as client: try: print(f"Connected to {target_device.name} ({target_device.address})") # Check if the notify characteristic exists services = client.services # Correct way to get characteristics characteristics = [] for service in services: characteristics.extend(service.characteristics) # Check for required characteristics characteristic_uuids = [char.uuid for char in characteristics] if NOTIFY_UUID not in characteristic_uuids or WRITE_UUID not in characteristic_uuids: print(f"Required characteristics not found in device services.") return # Subscribe to notifications print(f"Subscribing to notifications on {NOTIFY_UUID}...") await client.start_notify(NOTIFY_UUID, notification_handler) # Start write loop in parallel print(f"Starting Keep Alive Loop to {WRITE_UUID}...") write_task = asyncio.create_task(write_loop(client)) await write_and_read(client, command_list["get_brightness"]) await write_and_read(client, command_list["set_brightness"] + "01") #await write_and_read(client, command_list["set_scene"] + scenes["Romantic"]) #33 051501 6496c8 0000000000 3200 00000000002a # RRGGBB SEG # ff7f = all segments sleep_time = 5 await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time) #Set all to white await write_and_read(client, command_list["set_color"] + "FFFFFF" + "0000000000" + "ff7f") #Set 0th segment of 6 LEDs to red await asyncio.sleep(sleep_time) await write_and_read(client, command_list["set_color"] + "FF0000" + "0000000000" + segemnts2num([0])) await asyncio.sleep(sleep_time) #Set 1th and last segment of 6 LEDs to green await write_and_read(client, command_list["set_color"] + "00FF00" + "0000000000" + segemnts2num([1,14])) await asyncio.sleep(sleep_time) print("Running. Press Ctrl+C to stop.") while True: await asyncio.sleep(1) except KeyboardInterrupt: print("Stopping...") except Exception as e: print(f"Error during operation: {e}") finally: print("Cleaning up...") if client.is_connected: try: await client.stop_notify(NOTIFY_UUID) except Exception as e: print(f"Error stopping notifications: {e}") print("Disconnected.") # Run the async function try: asyncio.run(find_and_subscribe()) except KeyboardInterrupt: print("Program stopped by user.")